﻿// <copyright file="DataPoint.cs" company="Oleg V. Polikarpotchkin">
// Copyright © 2008-2009 Oleg V. Polikarpotchkin. All Right Reserved
// </copyright>
// <author>Oleg V. Polikarpotchkin</author>
// <email>ov-p@yandex.ru</email>
// <date>2009-01-17</date>
// <summary>OpenWPFChart library. DataPoint structure.</summary>
// <revision>$Id$</revision>

using System;

namespace OpenWPFChart.Parts
{
	/// <summary>
	/// 2D Data Point.
	/// </summary>
	/// <typeparam name="TX">The type of the abscissa.</typeparam>
	/// <typeparam name="TY">The type of the ordinate.</typeparam>
	public struct DataPoint<TX, TY>
	{
		/// <summary>
		/// Initializes a new instance of the DataPoint struct.
		/// </summary>
		/// <param name="x">The abscissa.</param>
		/// <param name="y">The ordinate.</param>
		public DataPoint(TX x, TY y)
		{
			this.x = x;
			this.y = y;
		}

		private readonly TX x;
		/// <summary>
		/// Gets the abscissa.
		/// </summary>
		/// <value>The abscissa.</value>
		public TX X { get { return x; } }

		private readonly TY y;
		/// <summary>
		/// Gets the ordinate.
		/// </summary>
		/// <value>The ordinate.</value>
		public TY Y { get { return y; } }

		/// <summary>
		/// Gets the value of <paramref name="index"/>-th dimension.
		/// </summary>
		/// <value></value>
		public object this[int index]
		{
			get
			{
				if (index < 0 || index > 1)
					throw new ArgumentOutOfRangeException("index");
				if (index == 0)
					return X;
				else
					return Y;
			}
		}

		#region object overrides
		/// <summary>
		/// Indicates whether this instance and a specified object are equal.
		/// </summary>
		/// <param name="obj">Another object to compare to.</param>
		/// <returns>
		/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
		/// </returns>
		public override bool Equals(object obj)
		{
			if (obj == null || obj.GetType() != typeof(DataPoint<TX, TY>))
				return false;
			DataPoint<TX, TY> pt = (DataPoint<TX, TY>)obj;
			return (X.Equals(pt.X) && Y.Equals(pt.Y));
		}

		/// <summary>
		/// Returns the hash code for this instance.
		/// </summary>
		/// <returns>
		/// A 32-bit signed integer that is the hash code for this instance.
		/// </returns>
		public override int GetHashCode()
		{
			return (X.GetHashCode() ^ Y.GetHashCode());
		}

		/// <summary>
		/// Returns this instance string representation.
		/// </summary>
		/// <returns>this instance <see cref="T:System.String"/> representation.</returns>
		public override string ToString()
		{
			return string.Format("({0},{1})", X, Y);
		}
		#endregion object overrides
	}

	/// <summary>
	/// 3D Data Point.
	/// </summary>
	/// <typeparam name="TX">The type of the abscissa.</typeparam>
	/// <typeparam name="TY">The type of the ordinate.</typeparam>
	/// <typeparam name="TZ">The type of the z-coordinate.</typeparam>
	public struct DataPoint<TX, TY, TZ>
	{
		/// <summary>
		/// Initializes a new instance of the DataPoint struct.
		/// </summary>
		/// <param name="x">The abscissa.</param>
		/// <param name="y">The ordinate.</param>
		/// <param name="z">The z-coordinate.</param>
		public DataPoint(TX x, TY y, TZ z)
		{
			this.x = x;
			this.y = y;
			this.z = z;
		}

		private readonly TX x;
		/// <summary>
		/// Gets the abscissa.
		/// </summary>
		/// <value>The abscissa.</value>
		public TX X { get { return x; } }

		private readonly TY y;
		/// <summary>
		/// Gets the ordinate.
		/// </summary>
		/// <value>The ordinate.</value>
		public TY Y { get { return y; } }

		private readonly TZ z;
		/// <summary>
		/// Gets the z-coordinate.
		/// </summary>
		/// <value>The z-coordinate.</value>
		public TZ Z { get { return z; } }

		/// <summary>
		/// Gets the value of <paramref name="index"/>-th dimension.
		/// </summary>
		/// <value></value>
		public object this[int index]
		{
			get
			{
				if (index < 0 || index > 2)
					throw new ArgumentOutOfRangeException("index");
				switch (index)
				{
					case 0:
						return X;
					case 1:
						return Y;
					default:
						return Z;
				}
			}
		}

		#region object overrides
		/// <summary>
		/// Indicates whether this instance and a specified object are equal.
		/// </summary>
		/// <param name="obj">Another object to compare to.</param>
		/// <returns>
		/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
		/// </returns>
		public override bool Equals(object obj)
		{
			if (obj == null || obj.GetType() != typeof(DataPoint<TX, TY, TZ>))
				return false;
			DataPoint<TX, TY, TZ> pt = (DataPoint<TX, TY, TZ>)obj;
			return (X.Equals(pt.X) && Y.Equals(pt.Y) &&Z.Equals(pt.Z));
		}

		/// <summary>
		/// Returns the hash code for this instance.
		/// </summary>
		/// <returns>
		/// A 32-bit signed integer that is the hash code for this instance.
		/// </returns>
		public override int GetHashCode()
		{
			return (X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode());
		}

		/// <summary>
		/// Returns this instance string representation.
		/// </summary>
		/// <returns>this instance <see cref="T:System.String"/> representation.</returns>
		public override string ToString()
		{
			return string.Format("({0},{1},{2})", X, Y, Z);
		}
		#endregion object overrides
	}
}
